UE.plugins['formatmatch'] = function() {
  var me = this
  var list = []
  var img
  var flag = 0
  me.addListener('reset', function() {
    list = []
    flag = 0
  })

  function addList(type, evt) {
    if (browser.webkit) {
      var target = evt.target.tagName == 'IMG' ? evt.target : null
    }

    function addFormat(range) {
      if (text) {
        range.selectNode(text)
      }
      return range.applyInlineStyle(list[list.length - 1].tagName, null, list)
    }

    me.undoManger && me.undoManger.save()
    var range = me.selection.getRange()
    var imgT = target || range.getClosedNode()
    if (img && imgT && imgT.tagName == 'IMG') {
      imgT.style.cssText +=
        ';float:' +
        (img.style.cssFloat || img.style.styleFloat || 'none') +
        ';display:' +
        (img.style.display || 'inline')
      img = null
    } else {
      if (!img) {
        var collapsed = range.collapsed
        if (collapsed) {
          var text = me.document.createTextNode('match')
          range.insertNode(text).select()
        }
        me.__hasEnterExecCommand = true
        var removeFormatAttributes = me.options.removeFormatAttributes
        me.options.removeFormatAttributes = ''
        me.execCommand('removeformat')
        me.options.removeFormatAttributes = removeFormatAttributes
        me.__hasEnterExecCommand = false
        range = me.selection.getRange()
        if (list.length) {
          addFormat(range)
        }
        if (text) {
          range.setStartBefore(text).collapse(true)
        }
        range.select()
        text && domUtils.remove(text)
      }
    }
    me.undoManger && me.undoManger.save()
    me.removeListener('mouseup', addList)
    flag = 0
  }

  me.commands['formatmatch'] = {
    execCommand: function(cmdName) {
      if (flag) {
        flag = 0
        list = []
        me.removeListener('mouseup', addList)
        return
      }
      var range = me.selection.getRange()
      img = range.getClosedNode()
      if (!img || img.tagName != 'IMG') {
        range.collapse(true).shrinkBoundary()
        var start = range.startContainer
        list = domUtils.findParents(start, true, function(node) {
          return !domUtils.isBlockElm(node) && node.nodeType == 1
        })
        for (var i = 0, ci; (ci = list[i]); i++) {
          if (ci.tagName == 'A') {
            list.splice(i, 1)
            break
          }
        }
      }
      me.addListener('mouseup', addList)
      flag = 1
    },
    queryCommandState: function() {
      return flag
    },
    notNeedUndo: 1
  }
}

UE.plugins['removeformat'] = function() {
  var me = this
  me.setOpt({
    removeFormatAttributes: 'class,style,lang,width,height,align,hspace,valign'
  })
  me.commands['removeformat'] = {
    execCommand: function(cmdName, tags, style, attrs, notIncludeA) {
      var tagReg = new RegExp('^(?:' + (tags || this.options.removeFormatTags).replace(/,/g, '|') + ')$', 'i')
      var removeFormatAttributes = style ? [] : (attrs || this.options.removeFormatAttributes).split(',')
      var range = new dom.Range(this.document)
      var bookmark
      var node
      var parent
      var filter = function(node) {
        return node.nodeType == 1
      }

      function isRedundantSpan(node) {
        if (node.nodeType == 3 || node.tagName.toLowerCase() != 'span') {
          return 0
        }
        if (browser.ie) {
          var attrs = node.attributes
          if (attrs.length) {
            for (var i = 0, l = attrs.length; i < l; i++) {
              if (attrs[i].specified) {
                return 0
              }
            }
            return 1
          }
        }
        return !node.attributes.length
      }

      function doRemove(range) {
        var bookmark1 = range.createBookmark()
        if (range.collapsed) {
          range.enlarge(true)
        }
        if (!notIncludeA) {
          var aNode = domUtils.findParentByTagName(range.startContainer, 'a', true)
          if (aNode) {
            range.setStartBefore(aNode)
          }
          aNode = domUtils.findParentByTagName(range.endContainer, 'a', true)
          if (aNode) {
            range.setEndAfter(aNode)
          }
        }
        bookmark = range.createBookmark()
        node = bookmark.start
        while ((parent = node.parentNode) && !domUtils.isBlockElm(parent)) {
          domUtils.breakParent(node, parent)
          domUtils.clearEmptySibling(node)
        }
        if (bookmark.end) {
          node = bookmark.end
          while ((parent = node.parentNode) && !domUtils.isBlockElm(parent)) {
            domUtils.breakParent(node, parent)
            domUtils.clearEmptySibling(node)
          }
          var current = domUtils.getNextDomNode(bookmark.start, false, filter)
          var next
          while (current) {
            if (current == bookmark.end) {
              break
            }
            next = domUtils.getNextDomNode(current, true, filter)
            if (!dtd.$empty[current.tagName.toLowerCase()] && !domUtils.isBookmarkNode(current)) {
              if (tagReg.test(current.tagName)) {
                if (style) {
                  domUtils.removeStyle(current, style)
                  if (isRedundantSpan(current) && style != 'text-decoration') {
                    domUtils.remove(current, true)
                  }
                } else {
                  domUtils.remove(current, true)
                }
              } else {
                if (!dtd.$tableContent[current.tagName] && !dtd.$list[current.tagName]) {
                  domUtils.removeAttributes(current, removeFormatAttributes)
                  if (isRedundantSpan(current)) {
                    domUtils.remove(current, true)
                  }
                }
              }
            }
            current = next
          }
        }
        var pN = bookmark.start.parentNode
        if (domUtils.isBlockElm(pN) && !dtd.$tableContent[pN.tagName] && !dtd.$list[pN.tagName]) {
          domUtils.removeAttributes(pN, removeFormatAttributes)
        }
        pN = bookmark.end.parentNode
        if (bookmark.end && domUtils.isBlockElm(pN) && !dtd.$tableContent[pN.tagName] && !dtd.$list[pN.tagName]) {
          domUtils.removeAttributes(pN, removeFormatAttributes)
        }
        range.moveToBookmark(bookmark).moveToBookmark(bookmark1)
        var node = range.startContainer
        var tmp
        var collapsed = range.collapsed
        while (node.nodeType == 1 && domUtils.isEmptyNode(node) && dtd.$removeEmpty[node.tagName]) {
          tmp = node.parentNode
          range.setStartBefore(node)
          if (range.startContainer === range.endContainer) {
            range.endOffset--
          }
          domUtils.remove(node)
          node = tmp
        }
        if (!collapsed) {
          node = range.endContainer
          while (node.nodeType == 1 && domUtils.isEmptyNode(node) && dtd.$removeEmpty[node.tagName]) {
            tmp = node.parentNode
            range.setEndBefore(node)
            domUtils.remove(node)
            node = tmp
          }
        }
      }

      range = this.selection.getRange()
      doRemove(range)
      range.select()
    }
  }
}

UE.commands['formatstandard'] = {
  execCommand: function(cmdName, tags, style, attrs, notIncludeA) {
    if (!confirm('一键标准格式化')) {
      return
    }
    let me = this
    let copyHtmlBody = me.body.innerHTML
    let range = me.selection.getRange()
    const regex = /style="([^"]*)(font-size:[^;"]*)([^"]*);?/g

    copyHtmlBody = copyHtmlBody.replace(regex, (match, prefix, fontSize, suffix) => {
      if (fontSize.indexOf('18px') > -1) {
        return match
      } else {
        return match.replaceAll(fontSize, 'font-size: 18px')
      }
    })
    copyHtmlBody = copyHtmlBody.replace(/style="([^"]*)(font-family:[^;"]*)([^"]*);?/g, (match, prefix, fontSize, suffix) => {
      if (fontSize === 'font-family: 宋体') {
        return match
      } else {
        return match.replaceAll(fontSize, 'font-family: 宋体')
      }
    })

    copyHtmlBody = copyHtmlBody.replace(/style="([^"]*)(line-height:[^;"]*)([^"]*);?/g, (match, prefix, fontSize, suffix) => {
      if (fontSize.indexOf('1.75em') > -1) {
        return match
      } else {
        return match.replaceAll(fontSize, 'line-height: 1.75em')
      }
    })

    me.body.innerHTML = `<p style="font-size: 18px;font-family: "宋体";line-height: 1.75em">` + copyHtmlBody + `</p>`
    range.setStart(me.body.firstChild, 0).setCursor(false, true)
    // // range.setStart(me.body.firstChild, 0).setCursor(false, true)
    // if (confirm('一键标准格式化')) {
    //   // 先恢复
    //   for (i = 0; i < fullangles.length; i++) {
    //     copyHtmlBody = copyHtmlBody.replaceAll('<span style="color:white;background: indianred">' + fullangles[i] + '</span>', fullangles[i])
    //   }
    //   // 再赋值
    //   for (i = 0; i < fullangles.length; i++) {
    //     copyHtmlBody = copyHtmlBody.replaceAll(fullangles[i], '<span style="color:white;background: indianred">' + fullangles[i] + '</span>')
    //   }
    //   // 优化去除
    //   // copyHtmlBody = copyHtmlBody.replaceAll('</span><span style="color:indianred">', '')
    //   console.log('fullangle', copyHtmlBody)
    //   me.body.innerHTML = copyHtmlBody
    //   range.setStart(me.body.firstChild, 0).setCursor(false, true)
    // }

    setTimeout(function() {
      me.fireEvent('formatstandard')
    }, 5)
  }
}